/**
  ******************************************************************************
  * @file    sym32l010_hal_lptim.c
  * @author  AE Team
  * @version 1.0.3
  * @date    2024-05-28
  * @brief   LPITM HAL module driver.
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 SIYIMicro.
  * All rights reserved.</center></h2>
  *
  *
  ******************************************************************************
  */


/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "sym32l010_hal_lptim.h"


/******************************************************************************/
/* global static variables                                                    */
/******************************************************************************/
static uint32_t gStartMode;

/*******************************************************************************
  * @brief  LPTIM 初始化
  * @param  InitStruct: 初始化结构体
  * @retval None
  * @note   需通过APBEN2寄存器使能LPTIM的时钟后，才可调用该函数
  */
void HAL_LPTIM_Init(LPTIM_InitTypeDef *InitStruct)
{
    gStartMode = InitStruct->StartMode;

    SYM_LPTIM->CFGR = (uint32_t)InitStruct->ICLKSource  | (uint32_t)InitStruct->PreLoad |
                      (uint32_t)InitStruct->Prescaler   | (uint32_t)InitStruct->TriggerMode |
                      (uint32_t)InitStruct->WorkMode;
    SYM_LPTIM->CR  = LPTIM_CR_EN_Msk | LPTIM_CR_ARST_Msk | LPTIM_CR_SRST_Msk;
    SYM_LPTIM->ARR = InitStruct->Reload;

    //while (HAL_LPTIM_GET_FLAG(LPTIM_IT_FLAG_ARROK) == 0x00) { ; }   // 等待ARR更新完成
}


/*******************************************************************************
  * @brief  LPTIM 反初始化
  * @param  None
  * @retval None
  */
void HAL_LPTIM_DeInit(void)
{
    REGBITS_CLR(SYM_SYSCTRL->APBRST2, SYSCTRL_APBRST2_LPTIM_Msk);
    REGBITS_SET(SYM_SYSCTRL->APBRST2, SYSCTRL_APBRST2_LPTIM_Msk);
}


/*******************************************************************************
  * @brief  LPTIM 编码器配置
  * @param  InitStruct: 配置结构体
  * @retval None
  * @note   需通过APBEN2寄存器使能LPTIM的时钟后，才可调用该函数
  */
void HAL_LPTIM_Encoder_Config(LPTIM_EncConfigTypeDef *InitStruct)
{
    REGBITS_MODIFY(SYM_LPTIM->CFGR, LPTIM_CFGR_ENCMD_CKPOL_Msk    | LPTIM_CFGR_CHFLT_Msk ,
                                    (uint32_t)InitStruct->EncMode | (uint32_t)InitStruct->CHxFilter);
}


/*******************************************************************************
  * @brief  LPTIM 触发配置
  * @param  InitStruct: 配置结构体
  * @retval None
  * @note   需通过APBEN2寄存器使能LPTIM的时钟后，才可调用该函数
  */
void HAL_LPTIM_Trig_Config(LPTIM_TrigConfigTypeDef *InitStruct)
{
    REGBITS_MODIFY(SYM_LPTIM->CFGR,
                   LPTIM_CFGR_TRIGSEL_Msk | LPTIM_CFGR_TRIGFLT_Msk | LPTIM_CFGR_TIMOUT_Msk,
                   (uint32_t)InitStruct->TriggerSource | (uint32_t)InitStruct->TriggerFilter |
                   (uint32_t)InitStruct->TriggerTimeOutEn);
}


/*******************************************************************************
  * @brief  启动 LPTIM
  * @param  None
  * @retval None
  */
void HAL_LPTIM_Start(void)
{
    if (SYM_LPTIM->CFGR & LPTIM_CFGR_CKSEL_Msk)                       // 异步计数
    {
        SYM_LPTIM->CR = LPTIM_CR_EN_Msk | LPTIM_CR_SRST_Msk;          // 对计数器进行异步复位
        while ((SYM_LPTIM->CR & LPTIM_CR_ARST_Msk) == 0x00) { ; }     // 等待异步复位完成
    }
    else                                                              // 定时模式，同步计数，编码器
    {
        SYM_LPTIM->CR = LPTIM_CR_EN_Msk | LPTIM_CR_ARST_Msk;          // 对计数器进行同步复位
        while ((SYM_LPTIM->CR & LPTIM_CR_SRST_Msk) == 0x00) { ; }     // 等待同步复位完成
    }

    if (gStartMode == LPTIM_STARTMODE_CNT)                            // 持续运行
    {
        SYM_LPTIM->CR = LPTIM_CR_EN_Msk   | LPTIM_CR_CNTSTART_Msk |
                        LPTIM_CR_ARST_Msk | LPTIM_CR_SRST_Msk;
    }
    else                                                              // 单次运行
    {
        SYM_LPTIM->CR = LPTIM_CR_EN_Msk   | LPTIM_CR_SNGSTART_Msk |
                        LPTIM_CR_ARST_Msk | LPTIM_CR_SRST_Msk;
    }
}


/*******************************************************************************
  * @brief  停止 LPTIM
  * @param  None
  * @retval None
  */
void HAL_LPTIM_Stop(void)
{
    SYM_LPTIM->CR = LPTIM_CR_ARST_Msk | LPTIM_CR_SRST_Msk;
}


/*******************************************************************************
  * @brief  获取LPTIM的工作状态
  * @retval 当前定时器运行状态
  */
uint16_t HAL_LPTIM_IsRunning(void)
{
    return (SYM_LPTIM->CR & LPTIM_CR_EN_Msk);
}


/*******************************************************************************
  * @brief  LPTIM 延时 PclkCnt 个PCLK
  * @param  PclkCnt: 待延时的PCLK数量
  *         39 ~ 65535
  * @retval None
  * @note   该函数最少占用约39个PCLK时间，延时时间最低为39个PCLK的时间(Keil-Level1优化等级情况下)
  */
__INLINE void HAL_LPTIM_DelayPclk(uint16_t PclkCnt)
{
    if (PclkCnt < 39)
    {
        return ;
    }

    SYM_LPTIM->CFGR = 0x00;
    SYM_LPTIM->ARR  = PclkCnt - 39;                                             // PclkCnt大于39延时更加精确
    SYM_LPTIM->CMP  = PclkCnt - 39;                                             // PclkCnt大于39延时更加精确
    SYM_LPTIM->CR   = LPTIM_CR_EN_Msk   | LPTIM_CR_SNGSTART_Msk | 
                      LPTIM_CR_ARST_Msk | LPTIM_CR_SRST_Msk;                    // 启动单次模式
    while ((SYM_LPTIM->ISR & LPTIM_ISR_CMPM_Msk) != LPTIM_ISR_CMPM_Msk) { ; }   // 等待计数完成
    SYM_LPTIM->ICR  = 0x00;                                                     // 清比较匹配标志
}


/*******************************************************************************
  * @brief  获取LPTIM的的当前计数器值
  * @param  None
  * @retval 当前计数值
  */
uint16_t HAL_LPTIM_GetCounterValue(void)
{
    uint32_t Cnt1, Cnt2;
    do
    {
        Cnt1 = SYM_LPTIM->CNT;
        Cnt2 = SYM_LPTIM->CNT;
    } while (Cnt1 != Cnt2);

    return (uint16_t)Cnt1;
}


/*******************************************************************************
  * @brief  设置LPTIM的ARR值
  * @param  ArrValue: ARR设定值
  * @retval None
  */
void HAL_LPTIM_SetReloadValue(uint16_t ArrValue)
{
    SYM_LPTIM->ARR = ArrValue;
    while (HAL_LPTIM_GET_FLAG(LPTIM_IT_FLAG_ARROK) == 0x00) { ; }
}


/*******************************************************************************
  * @brief  设置LPTIM的CMP值
  * @param  CmpValue: CMP寄存器设定值
  * @retval None
  */
void HAL_LPTIM_SetCompareValue(uint16_t CmpValue)
{
    SYM_LPTIM->CMP = CmpValue;
    while (HAL_LPTIM_GET_FLAG(LPTIM_IT_FLAG_CMPOK) == 0x00) { ; }
}


/*******************************************************************************
  * @brief  获取LPTIM的CMP值
  * @param  None
  * @retval 当前比较值
  */
uint16_t HAL_LPTIM_GetCompareValue(void)
{
    return SYM_LPTIM->CMP;
}


/*******************************************************************************
  * @brief  LPTIM输出波形配置
  * @param  WavePolarity: LPTIM输出波形的极性
  *                       @arg LPTIM_WAVEPOL_POSITIVE
  *                       @arg LPTIM_WAVEPOL_NEGATIVE
  * @param      WaveType: LPTIM输出波形使能控制
  *                       @arg LTPTIM_WAVE_DISABLE
  *                       @arg LTPTIM_WAVE_ENABLE
  * @retval None
  */
void HAL_LPTIM_WaveForm_Config(LPTIM_WavePolarityTypeDef WavePolarity, LPTIM_WaveTypeDef WaveType)
{
    REGBITS_MODIFY(SYM_LPTIM->CFGR, LPTIM_CFGR_WAVPOL_Msk   |  LPTIM_CFGR_WAVE_Msk,
                                    (uint32_t)WavePolarity  |  (uint32_t)WaveType);
}


/*******************************************************************************
  * @brief  LPTIM计数器通道配置,CH1计数边沿，CHx滤波时间
  * @param  ChEdge: CH1信号计数边沿模式
  *                 @arg LPTIM_CKPOL_RISE
  *                 @arg LPTIM_CKPOL_FALL
  *                 @arg LPTIM_CKPOL_BOTH
  * @param  FltClk: CH1/CH2通道数字滤波设置
  *                 @arg LPTIM_CHxFLT_NONE
  *                 @arg LPTIM_CHxFLT_ICLK2
  *                 @arg LPTIM_CHxFLT_ICLK4
  *                 @arg LPTIM_CHxFLT_ICLK8
  * @retval None
  */
void HAL_LPTIM_Channelx_Config(LPTIM_Ch1EdgeTypeDef ChEdge, LPTIM_CHxFilterTypeDef FltClk)
{
    REGBITS_MODIFY(SYM_LPTIM->CFGR, LPTIM_CFGR_ENCMD_CKPOL_Msk | LPTIM_CFGR_CHFLT_Msk,
                                    (uint32_t)ChEdge           | (uint32_t)FltClk);
}


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
